﻿using System.Text;

namespace Unikado.PHPLibs.Tokenizer.Highlighter
{

    /// <summary>
    /// The PHP Highlighter configuration
    /// </summary>
    /// <remarks>
    /// <para>How to use:</para>
    /// <code>
    /// var tokens = PhpTokenizer.ParseFile(@"C:\path\to\phpfile.php");
    /// var cfg = new HighlighterConfig();
    /// cfg.ConfigRules[HighlighterTokenType.Bracket].ForeColor = "brown";
    /// cfg.ConfigRules[HighlighterTokenType.Comment].ForeColor = "darkorange";
    /// cfg.ConfigRules[HighlighterTokenType.DocBlock].ForeColor = "orange";
    /// cfg.ConfigRules[HighlighterTokenType.Keyword].ForeColor = "blue";
    /// cfg.ConfigRules[HighlighterTokenType.Keyword].Bold = true;
    /// cfg.ConfigRules[HighlighterTokenType.MagicConstant].ForeColor = "violet";
    /// cfg.ConfigRules[HighlighterTokenType.NoPhp].ForeColor = "darkgray";
    /// cfg.ConfigRules[HighlighterTokenType.Number].ForeColor = "red";
    /// cfg.ConfigRules[HighlighterTokenType.Operator].ForeColor = "firebrick";
    /// cfg.ConfigRules[HighlighterTokenType.PhpClass].ForeColor = "royalblue";
    /// cfg.ConfigRules[HighlighterTokenType.PhpFunction].ForeColor = "royalblue";
    /// cfg.ConfigRules[HighlighterTokenType.PhpInterface].ForeColor = "royalblue";
    /// cfg.ConfigRules[HighlighterTokenType.PhpTag].ForeColor = "red";
    /// cfg.ConfigRules[HighlighterTokenType.PhpTag].Bold = true;
    /// cfg.ConfigRules[HighlighterTokenType.String].ForeColor = "gray";
    /// cfg.ConfigRules[HighlighterTokenType.SuperGlobal].ForeColor = "violet";
    /// cfg.ConfigRules[HighlighterTokenType.Variable].ForeColor = "green";
    /// webBrowser1.DocumentText = cfg.CreateHtml5(tokens, Path.GetFileName(textBox1.Text));
    /// </code>
    /// </remarks>
    public class HighlighterConfig
    {

        #region - - - - - -   P U B L I C   P R O P E R T I E S   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        /// <summary>
        /// All current defined config rules.
        /// </summary>
        public HighlighterTypeConfigs ConfigRules { get; private set; }
        /// <summary>
        /// The Default text color for PHP code without a special meaning
        /// </summary>
        public string DefaultColor { get; set; }
        /// <summary>
        /// CSS Fontfamily names to use for displaying the code.
        /// </summary>
        public string FontFamily { get; set; }

        #endregion

        #region - - - - - -   C O N S T R U C T O R S   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        /// <summary>
        /// Inits a new instance.
        /// </summary>
        /// <param name="defaultColor">The Default text color for PHP code without a special meaning</param>
        /// <param name="fontFamily">CSS Fontfamily names to use for displaying the code.</param>
        public HighlighterConfig(string defaultColor = "#000", string fontFamily = "Consolas, monospace")
        {
            ConfigRules = new HighlighterTypeConfigs();
            DefaultColor = string.IsNullOrEmpty(defaultColor) ? "#000" : defaultColor;
            FontFamily = string.IsNullOrEmpty(fontFamily) ? "Consolas, monospace" : fontFamily;
        }

        #endregion

        #region - - - - - -   P U B L I C   M E T H O D S   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        /// <summary>
        /// Creates the whole content of a HTML5 document.
        /// </summary>
        /// <param name="tokens">All Tokens to show as a highlighted PHP source</param>
        /// <param name="documentTitle">The title for the HTML document.</param>
        /// <returns>The document contents als a string.</returns>
        public string CreateHtml5(TokenCollection tokens, string documentTitle)
        {
            var sb = new StringBuilder();
            sb.Append(@"<!DOCTYPE html>
<html lang=""en"">
  <head>
    <meta charset=""utf-8"">
    <meta http-equiv=""X-UA-Compatible"" content=""IE=edge,chrome=1"">
    <title>".Replace("\r\n", "\n"));
            sb.Append(HighlighterTypeConfig.EscapeForHtml(documentTitle));
            sb.Append(@"</title>
    <meta name=""viewport"" content=""width=device-width; initial-scale=1.0"">
    <style type=""text/css"">".Replace("\r\n", "\n"));
            sb.Append("\npre { color: ").Append(DefaultColor).Append("; font-family: ").Append(FontFamily).
               Append("; font-size: .9em; border: 1px dashed gray; background-color: whitesmoke; padding: 1em; }");
            ConfigRules.WriteCssRules(ref sb);
            sb.Append("\n    </style>\n  </head>\n  <body>\n    <h1>");
            sb.Append(documentTitle).Append("</h1>\n    <pre>");
            foreach (var tok in tokens)
            {
                if (ConfigRules.WriteHtml(tok, ref sb)) continue;
                sb.Append(HighlighterTypeConfig.EscapeForHtml(tok.Text));
            }
            sb.Append("</pre>\n  </body>\n</html>");
            return sb.ToString();
        }

        #endregion

    }

}